home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / PEAR / Config.php < prev    next >
PHP Script  |  2004-10-01  |  35KB  |  1,170 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 5                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Stig Bakken <ssb@php.net>                                    |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Config.php,v 1.52 2004/01/08 17:33:12 sniper Exp $
  20.  
  21. require_once 'PEAR.php';
  22. require_once 'System.php';
  23.  
  24. /**
  25.  * Last created PEAR_Config instance.
  26.  * @var object
  27.  */
  28. $GLOBALS['_PEAR_Config_instance'] = null;
  29. if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
  30.     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
  31. } else {
  32.     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
  33. }
  34.  
  35. // Below we define constants with default values for all configuration
  36. // parameters except username/password.  All of them can have their
  37. // defaults set through environment variables.  The reason we use the
  38. // PHP_ prefix is for some security, PHP protects environment
  39. // variables starting with PHP_*.
  40.  
  41. if (getenv('PHP_PEAR_SYSCONF_DIR')) {
  42.     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
  43. } elseif (getenv('SystemRoot')) {
  44.     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
  45. } else {
  46.     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
  47. }
  48.  
  49. // Default for master_server
  50. if (getenv('PHP_PEAR_MASTER_SERVER')) {
  51.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
  52. } else {
  53.     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
  54. }
  55.  
  56. // Default for http_proxy
  57. if (getenv('PHP_PEAR_HTTP_PROXY')) {
  58.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
  59. } elseif (getenv('http_proxy')) {
  60.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
  61. } else {
  62.     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
  63. }
  64.  
  65. // Default for php_dir
  66. if (getenv('PHP_PEAR_INSTALL_DIR')) {
  67.     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
  68. } else {
  69.     if (@is_dir($PEAR_INSTALL_DIR)) {
  70.         define('PEAR_CONFIG_DEFAULT_PHP_DIR',
  71.                $PEAR_INSTALL_DIR);
  72.     } else {
  73.         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
  74.     }
  75. }
  76.  
  77. // Default for ext_dir
  78. if (getenv('PHP_PEAR_EXTENSION_DIR')) {
  79.     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
  80. } else {
  81.     if (ini_get('extension_dir')) {
  82.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
  83.     } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) {
  84.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
  85.     } elseif (defined('PHP_EXTENSION_DIR')) {
  86.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
  87.     } else {
  88.         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
  89.     }
  90. }
  91.  
  92. // Default for doc_dir
  93. if (getenv('PHP_PEAR_DOC_DIR')) {
  94.     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
  95. } else {
  96.     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
  97.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
  98. }
  99.  
  100. // Default for bin_dir
  101. if (getenv('PHP_PEAR_BIN_DIR')) {
  102.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
  103. } else {
  104.     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
  105. }
  106.  
  107. // Default for data_dir
  108. if (getenv('PHP_PEAR_DATA_DIR')) {
  109.     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
  110. } else {
  111.     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
  112.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
  113. }
  114.  
  115. // Default for test_dir
  116. if (getenv('PHP_PEAR_TEST_DIR')) {
  117.     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
  118. } else {
  119.     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
  120.            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
  121. }
  122.  
  123. // Default for cache_dir
  124. if (getenv('PHP_PEAR_CACHE_DIR')) {
  125.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
  126. } else {
  127.     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
  128.            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
  129.            DIRECTORY_SEPARATOR . 'cache');
  130. }
  131.  
  132. // Default for php_bin
  133. if (getenv('PHP_PEAR_PHP_BIN')) {
  134.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
  135. } else {
  136.     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
  137.            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
  138. }
  139.  
  140. // Default for verbose
  141. if (getenv('PHP_PEAR_VERBOSE')) {
  142.     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
  143. } else {
  144.     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
  145. }
  146.  
  147. // Default for preferred_state
  148. if (getenv('PHP_PEAR_PREFERRED_STATE')) {
  149.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
  150. } else {
  151.     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
  152. }
  153.  
  154. // Default for umask
  155. if (getenv('PHP_PEAR_UMASK')) {
  156.     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
  157. } else {
  158.     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
  159. }
  160.  
  161. // Default for cache_ttl
  162. if (getenv('PHP_PEAR_CACHE_TTL')) {
  163.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
  164. } else {
  165.     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
  166. }
  167.  
  168. // Default for sig_type
  169. if (getenv('PHP_PEAR_SIG_TYPE')) {
  170.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
  171. } else {
  172.     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
  173. }
  174.  
  175. // Default for sig_bin
  176. if (getenv('PHP_PEAR_SIG_BIN')) {
  177.     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
  178. } else {
  179.     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
  180.            System::which(
  181.                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
  182. }
  183.  
  184. // Default for sig_keydir
  185. if (getenv('PHP_PEAR_SIG_KEYDIR')) {
  186.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
  187. } else {
  188.     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
  189.            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
  190. }
  191.  
  192. /**
  193.  * This is a class for storing configuration data, keeping track of
  194.  * which are system-defined, user-defined or defaulted.
  195.  */
  196. class PEAR_Config extends PEAR
  197. {
  198.     // {{{ properties
  199.  
  200.     /**
  201.      * Array of config files used.
  202.      *
  203.      * @var array layer => config file
  204.      */
  205.     var $files = array(
  206.         'system' => '',
  207.         'user' => '',
  208.         );
  209.  
  210.     var $layers = array();
  211.  
  212.     /**
  213.      * Configuration data, two-dimensional array where the first
  214.      * dimension is the config layer ('user', 'system' and 'default'),
  215.      * and the second dimension is keyname => value.
  216.      *
  217.      * The order in the first dimension is important!  Earlier
  218.      * layers will shadow later ones when a config value is
  219.      * requested (if a 'user' value exists, it will be returned first,
  220.      * then 'system' and finally 'default').
  221.      *
  222.      * @var array layer => array(keyname => value, ...)
  223.      */
  224.     var $configuration = array(
  225.         'user' => array(),
  226.         'system' => array(),
  227.         'default' => array(),
  228.         );
  229.  
  230.     /**
  231.      * Information about the configuration data.  Stores the type,
  232.      * default value and a documentation string for each configuration
  233.      * value.
  234.      *
  235.      * @var array layer => array(infotype => value, ...)
  236.      */
  237.     var $configuration_info = array(
  238.         // Internet Access
  239.         'master_server' => array(
  240.             'type' => 'string',
  241.             'default' => 'pear.php.net',
  242.             'doc' => 'name of the main PEAR server',
  243.             'prompt' => 'PEAR server',
  244.             'group' => 'Internet Access',
  245.             ),
  246.         'http_proxy' => array(
  247.             'type' => 'string',
  248.             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
  249.             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
  250.             'prompt' => 'HTTP Proxy Server Address',
  251.             'group' => 'Internet Access',
  252.             ),
  253.         // File Locations
  254.         'php_dir' => array(
  255.             'type' => 'directory',
  256.             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
  257.             'doc' => 'directory where .php files are installed',
  258.             'prompt' => 'PEAR directory',
  259.             'group' => 'File Locations',
  260.             ),
  261.         'ext_dir' => array(
  262.             'type' => 'directory',
  263.             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
  264.             'doc' => 'directory where loadable extensions are installed',
  265.             'prompt' => 'PHP extension directory',
  266.             'group' => 'File Locations',
  267.             ),
  268.         'doc_dir' => array(
  269.             'type' => 'directory',
  270.             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
  271.             'doc' => 'directory where documentation is installed',
  272.             'prompt' => 'PEAR documentation directory',
  273.             'group' => 'File Locations',
  274.             ),
  275.         'bin_dir' => array(
  276.             'type' => 'directory',
  277.             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
  278.             'doc' => 'directory where executables are installed',
  279.             'prompt' => 'PEAR executables directory',
  280.             'group' => 'File Locations',
  281.             ),
  282.         'data_dir' => array(
  283.             'type' => 'directory',
  284.             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
  285.             'doc' => 'directory where data files are installed',
  286.             'prompt' => 'PEAR data directory',
  287.             'group' => 'File Locations (Advanced)',
  288.             ),
  289.         'test_dir' => array(
  290.             'type' => 'directory',
  291.             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
  292.             'doc' => 'directory where regression tests are installed',
  293.             'prompt' => 'PEAR test directory',
  294.             'group' => 'File Locations (Advanced)',
  295.             ),
  296.         'cache_dir' => array(
  297.             'type' => 'directory',
  298.             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
  299.             'doc' => 'directory which is used for XMLRPC cache',
  300.             'prompt' => 'PEAR Installer cache directory',
  301.             'group' => 'File Locations (Advanced)',
  302.             ),
  303.         'php_bin' => array(
  304.             'type' => 'file',
  305.             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
  306.             'doc' => 'PHP CLI/CGI binary for executing scripts',
  307.             'prompt' => 'PHP CLI/CGI binary',
  308.             'group' => 'File Locations (Advanced)',
  309.             ),
  310.         // Maintainers
  311.         'username' => array(
  312.             'type' => 'string',
  313.             'default' => '',
  314.             'doc' => '(maintainers) your PEAR account name',
  315.             'prompt' => 'PEAR username (for maintainers)',
  316.             'group' => 'Maintainers',
  317.             ),
  318.         'password' => array(
  319.             'type' => 'password',
  320.             'default' => '',
  321.             'doc' => '(maintainers) your PEAR account password',
  322.             'prompt' => 'PEAR password (for maintainers)',
  323.             'group' => 'Maintainers',
  324.             ),
  325.         // Advanced
  326.         'verbose' => array(
  327.             'type' => 'integer',
  328.             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
  329.             'doc' => 'verbosity level
  330. 0: really quiet
  331. 1: somewhat quiet
  332. 2: verbose
  333. 3: debug',
  334.             'prompt' => 'Debug Log Level',
  335.             'group' => 'Advanced',
  336.             ),
  337.         'preferred_state' => array(
  338.             'type' => 'set',
  339.             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
  340.             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
  341.             'valid_set' => array(
  342.                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
  343.             'prompt' => 'Preferred Package State',
  344.             'group' => 'Advanced',
  345.             ),
  346.         'umask' => array(
  347.             'type' => 'mask',
  348.             'default' => PEAR_CONFIG_DEFAULT_UMASK,
  349.             'doc' => 'umask used when creating files (Unix-like systems only)',
  350.             'prompt' => 'Unix file mask',
  351.             'group' => 'Advanced',
  352.             ),
  353.         'cache_ttl' => array(
  354.             'type' => 'integer',
  355.             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
  356.             'doc' => 'amount of secs where the local cache is used and not updated',
  357.             'prompt' => 'Cache TimeToLive',
  358.             'group' => 'Advanced',
  359.             ),
  360.         'sig_type' => array(
  361.             'type' => 'set',
  362.             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
  363.             'doc' => 'which package signature mechanism to use',
  364.             'valid_set' => array('gpg'),
  365.             'prompt' => 'Package Signature Type',
  366.             'group' => 'Maintainers',
  367.             ),
  368.         'sig_bin' => array(
  369.             'type' => 'string',
  370.             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
  371.             'doc' => 'which package signature mechanism to use',
  372.             'prompt' => 'Signature Handling Program',
  373.             'group' => 'Maintainers',
  374.             ),
  375.         'sig_keyid' => array(
  376.             'type' => 'string',
  377.             'default' => '',
  378.             'doc' => 'which key to use for signing with',
  379.             'prompt' => 'Signature Key Id',
  380.             'group' => 'Maintainers',
  381.             ),
  382.         'sig_keydir' => array(
  383.             'type' => 'string',
  384.             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
  385.             'doc' => 'which package signature mechanism to use',
  386.             'prompt' => 'Signature Key Directory',
  387.             'group' => 'Maintainers',
  388.             ),
  389.         );
  390.  
  391.     // }}}
  392.  
  393.     // {{{ PEAR_Config([file], [defaults_file])
  394.  
  395.     /**
  396.      * Constructor.
  397.      *
  398.      * @param string (optional) file to read user-defined options from
  399.      * @param string (optional) file to read system-wide defaults from
  400.      *
  401.      * @access public
  402.      *
  403.      * @see PEAR_Config::singleton
  404.      */
  405.     function PEAR_Config($user_file = '', $system_file = '')
  406.     {
  407.         $this->PEAR();
  408.         $sl = DIRECTORY_SEPARATOR;
  409.         if (empty($user_file)) {
  410.             if (OS_WINDOWS) {
  411.                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
  412.             } else {
  413.                 $user_file = getenv('HOME') . $sl . '.pearrc';
  414.             }
  415.         }
  416.         if (empty($system_file)) {
  417.             if (OS_WINDOWS) {
  418.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
  419.             } else {
  420.                 $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
  421.             }
  422.         }
  423.         $this->layers = array_keys($this->configuration);
  424.         $this->files['user'] = $user_file;
  425.         $this->files['system'] = $system_file;
  426.         if ($user_file && file_exists($user_file)) {
  427.             $this->readConfigFile($user_file);
  428.         }
  429.         if ($system_file && file_exists($system_file)) {
  430.             $this->mergeConfigFile($system_file, false, 'system');
  431.         }
  432.         foreach ($this->configuration_info as $key => $info) {
  433.             $this->configuration['default'][$key] = $info['default'];
  434.         }
  435.         //$GLOBALS['_PEAR_Config_instance'] = &$this;
  436.     }
  437.  
  438.     // }}}
  439.     // {{{ singleton([file], [defaults_file])
  440.  
  441.     /**
  442.      * Static singleton method.  If you want to keep only one instance
  443.      * of this class in use, this method will give you a reference to
  444.      * the last created PEAR_Config object if one exists, or create a
  445.      * new object.
  446.      *
  447.      * @param string (optional) file to read user-defined options from
  448.      * @param string (optional) file to read system-wide defaults from
  449.      *
  450.      * @return object an existing or new PEAR_Config instance
  451.      *
  452.      * @access public
  453.      *
  454.      * @see PEAR_Config::PEAR_Config
  455.      */
  456.     function &singleton($user_file = '', $system_file = '')
  457.     {
  458.         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
  459.             return $GLOBALS['_PEAR_Config_instance'];
  460.         }
  461.         $GLOBALS['_PEAR_Config_instance'] =
  462.              &new PEAR_Config($user_file, $system_file);
  463.         return $GLOBALS['_PEAR_Config_instance'];
  464.     }
  465.  
  466.     // }}}
  467.     // {{{ readConfigFile([file], [layer])
  468.  
  469.     /**
  470.      * Reads configuration data from a file.  All existing values in
  471.      * the config layer are discarded and replaced with data from the
  472.      * file.
  473.      *
  474.      * @param string (optional) file to read from, if NULL or not
  475.      * specified, the last-used file for the same layer (second param)
  476.      * is used
  477.      *
  478.      * @param string (optional) config layer to insert data into
  479.      * ('user' or 'system')
  480.      *
  481.      * @return bool TRUE on success or a PEAR error on failure
  482.      *
  483.      * @access public
  484.      */
  485.     function readConfigFile($file = null, $layer = 'user')
  486.     {
  487.         if (empty($this->files[$layer])) {
  488.             return $this->raiseError("unknown config file type `$layer'");
  489.         }
  490.         if ($file === null) {
  491.             $file = $this->files[$layer];
  492.         }
  493.         $data = $this->_readConfigDataFrom($file);
  494.         if (PEAR::isError($data)) {
  495.             return $data;
  496.         }
  497.         $this->_decodeInput($data);
  498.         $this->configuration[$layer] = $data;
  499.         return true;
  500.     }
  501.  
  502.     // }}}
  503.     // {{{ mergeConfigFile(file, [override], [layer])
  504.  
  505.     /**
  506.      * Merges data into a config layer from a file.  Does the same
  507.      * thing as readConfigFile, except it does not replace all
  508.      * existing values in the config layer.
  509.      *
  510.      * @param string file to read from
  511.      *
  512.      * @param bool (optional) whether to overwrite existing data
  513.      * (default TRUE)
  514.      *
  515.      * @param string config layer to insert data into ('user' or
  516.      * 'system')
  517.      *
  518.      * @return bool TRUE on success or a PEAR error on failure
  519.      *
  520.      * @access public.
  521.      */
  522.     function mergeConfigFile($file, $override = true, $layer = 'user')
  523.     {
  524.         if (empty($this->files[$layer])) {
  525.             return $this->raiseError("unknown config file type `$layer'");
  526.         }
  527.         if ($file === null) {
  528.             $file = $this->files[$layer];
  529.         }
  530.         $data = $this->_readConfigDataFrom($file);
  531.         if (PEAR::isError($data)) {
  532.             return $data;
  533.         }
  534.         $this->_decodeInput($data);
  535.         if ($override) {
  536.             $this->configuration[$layer] = array_merge($this->configuration[$layer], $data);
  537.         } else {
  538.             $this->configuration[$layer] = array_merge($data, $this->configuration[$layer]);
  539.         }
  540.         return true;
  541.     }
  542.  
  543.     // }}}
  544.     // {{{ writeConfigFile([file], [layer])
  545.  
  546.     /**
  547.      * Writes data into a config layer from a file.
  548.      *
  549.      * @param string file to read from
  550.      *
  551.      * @param bool (optional) whether to overwrite existing data
  552.      * (default TRUE)
  553.      *
  554.      * @param string config layer to insert data into ('user' or
  555.      * 'system')
  556.      *
  557.      * @return bool TRUE on success or a PEAR error on failure
  558.      *
  559.      * @access public.
  560.      */
  561.     function writeConfigFile($file = null, $layer = 'user', $data = null)
  562.     {
  563.         if ($layer == 'both' || $layer == 'all') {
  564.             foreach ($this->files as $type => $file) {
  565.                 $err = $this->writeConfigFile($file, $type, $data);
  566.                 if (PEAR::isError($err)) {
  567.                     return $err;
  568.                 }
  569.             }
  570.             return true;
  571.         }
  572.         if (empty($this->files[$layer])) {
  573.             return $this->raiseError("unknown config file type `$layer'");
  574.         }
  575.         if ($file === null) {
  576.             $file = $this->files[$layer];
  577.         }
  578.         $data = ($data === null) ? $this->configuration[$layer] : $data;
  579.         $this->_encodeOutput($data);
  580.         $opt = array('-p', dirname($file));
  581.         if (!@System::mkDir($opt)) {
  582.             return $this->raiseError("could not create directory: " . dirname($file));
  583.         }
  584.         if (@is_file($file) && !@is_writeable($file)) {
  585.             return $this->raiseError("no write access to $file!");
  586.         }
  587.         $fp = @fopen($file, "w");
  588.         if (!$fp) {
  589.             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed");
  590.         }
  591.         $contents = "#PEAR_Config 0.9\n" . serialize($data);
  592.         if (!@fwrite($fp, $contents)) {
  593.             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed");
  594.         }
  595.         return true;
  596.     }
  597.  
  598.     // }}}
  599.     // {{{ _readConfigDataFrom(file)
  600.  
  601.     /**
  602.      * Reads configuration data from a file and returns the parsed data
  603.      * in an array.
  604.      *
  605.      * @param string file to read from
  606.      *
  607.      * @return array configuration data or a PEAR error on failure
  608.      *
  609.      * @access private
  610.      */
  611.     function _readConfigDataFrom($file)
  612.     {
  613.         $fp = @fopen($file, "r");
  614.         if (!$fp) {
  615.             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
  616.         }
  617.         $size = filesize($file);
  618.         $rt = get_magic_quotes_runtime();
  619.         set_magic_quotes_runtime(0);
  620.         $contents = fread($fp, $size);
  621.         set_magic_quotes_runtime($rt);
  622.         fclose($fp);
  623.         $version = '0.1';
  624.         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
  625.             $version = $matches[1];
  626.             $contents = substr($contents, strlen($matches[0]));
  627.         }
  628.         if (version_compare("$version", '1', '<')) {
  629.             $data = unserialize($contents);
  630.             if (!is_array($data)) {
  631.                 if (strlen(trim($contents)) > 0) {
  632.                     $error = "PEAR_Config: bad data in $file";
  633. //                if (isset($this)) {
  634.                     return $this->raiseError($error);
  635. //                } else {
  636. //                    return PEAR::raiseError($error);
  637.                 } else {
  638.                     $data = array();
  639.                 }
  640.             }
  641.         // add parsing of newer formats here...
  642.         } else {
  643.             return $this->raiseError("$file: unknown version `$version'");
  644.         }
  645.         return $data;
  646.     }
  647.  
  648.     // }}}
  649.     // {{{ getConfFile(layer)
  650.     /**
  651.     * Gets the file used for storing the config for a layer
  652.     *
  653.     * @param string $layer 'user' or 'system'
  654.     */
  655.  
  656.     function getConfFile($layer)
  657.     {
  658.         return $this->files[$layer];
  659.     }
  660.  
  661.     // }}}
  662.     // {{{ _encodeOutput(&data)
  663.  
  664.     /**
  665.      * Encodes/scrambles configuration data before writing to files.
  666.      * Currently, 'password' values will be base64-encoded as to avoid
  667.      * that people spot cleartext passwords by accident.
  668.      *
  669.      * @param array (reference) array to encode values in
  670.      *
  671.      * @return bool TRUE on success
  672.      *
  673.      * @access private
  674.      */
  675.     function _encodeOutput(&$data)
  676.     {
  677.         foreach ($data as $key => $value) {
  678.             if (!isset($this->configuration_info[$key])) {
  679.                 continue;
  680.             }
  681.             $type = $this->configuration_info[$key]['type'];
  682.             switch ($type) {
  683.                 // we base64-encode passwords so they are at least
  684.                 // not shown in plain by accident
  685.                 case 'password': {
  686.                     $data[$key] = base64_encode($data[$key]);
  687.                     break;
  688.                 }
  689.                 case 'mask': {
  690.                     $data[$key] = octdec($data[$key]);
  691.                     break;
  692.                 }
  693.             }
  694.         }
  695.         return true;
  696.     }
  697.  
  698.     // }}}
  699.     // {{{ _decodeInput(&data)
  700.  
  701.     /**
  702.      * Decodes/unscrambles configuration data after reading from files.
  703.      *
  704.      * @param array (reference) array to encode values in
  705.      *
  706.      * @return bool TRUE on success
  707.      *
  708.      * @access private
  709.      *
  710.      * @see PEAR_Config::_encodeOutput
  711.      */
  712.     function _decodeInput(&$data)
  713.     {
  714.         if (!is_array($data)) {
  715.             return true;
  716.         }
  717.         foreach ($data as $key => $value) {
  718.             if (!isset($this->configuration_info[$key])) {
  719.                 continue;
  720.             }
  721.             $type = $this->configuration_info[$key]['type'];
  722.             switch ($type) {
  723.                 case 'password': {
  724.                     $data[$key] = base64_decode($data[$key]);
  725.                     break;
  726.                 }
  727.                 case 'mask': {
  728.                     $data[$key] = decoct($data[$key]);
  729.                     break;
  730.                 }
  731.             }
  732.         }
  733.         return true;
  734.     }
  735.  
  736.     // }}}
  737.     // {{{ get(key, [layer])
  738.  
  739.     /**
  740.      * Returns a configuration value, prioritizing layers as per the
  741.      * layers property.
  742.      *
  743.      * @param string config key
  744.      *
  745.      * @return mixed the config value, or NULL if not found
  746.      *
  747.      * @access public
  748.      */
  749.     function get($key, $layer = null)
  750.     {
  751.         if ($layer === null) {
  752.             foreach ($this->layers as $layer) {
  753.                 if (isset($this->configuration[$layer][$key])) {
  754.                     return $this->configuration[$layer][$key];
  755.                 }
  756.             }
  757.         } elseif (isset($this->configuration[$layer][$key])) {
  758.             return $this->configuration[$layer][$key];
  759.         }
  760.         return null;
  761.     }
  762.  
  763.     // }}}
  764.     // {{{ set(key, value, [layer])
  765.  
  766.     /**
  767.      * Set a config value in a specific layer (defaults to 'user').
  768.      * Enforces the types defined in the configuration_info array.  An
  769.      * integer config variable will be cast to int, and a set config
  770.      * variable will be validated against its legal values.
  771.      *
  772.      * @param string config key
  773.      *
  774.      * @param string config value
  775.      *
  776.      * @param string (optional) config layer
  777.      *
  778.      * @return bool TRUE on success, FALSE on failure
  779.      *
  780.      * @access public
  781.      */
  782.     function set($key, $value, $layer = 'user')
  783.     {
  784.         if (empty($this->configuration_info[$key])) {
  785.             return false;
  786.         }
  787.         extract($this->configuration_info[$key]);
  788.         switch ($type) {
  789.             case 'integer':
  790.                 $value = (int)$value;
  791.                 break;
  792.             case 'set': {
  793.                 // If a valid_set is specified, require the value to
  794.                 // be in the set.  If there is no valid_set, accept
  795.                 // any value.
  796.                 if ($valid_set) {
  797.                     reset($valid_set);
  798.                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
  799.                         (key($valid_set) !== 0 && empty($valid_set[$value])))
  800.                     {
  801.                         return false;
  802.                     }
  803.                 }
  804.                 break;
  805.             }
  806.         }
  807.         $this->configuration[$layer][$key] = $value;
  808.         return true;
  809.     }
  810.  
  811.     // }}}
  812.     // {{{ getType(key)
  813.  
  814.     /**
  815.      * Get the type of a config value.
  816.      *
  817.      * @param string  config key
  818.      *
  819.      * @return string type, one of "string", "integer", "file",
  820.      * "directory", "set" or "password".
  821.      *
  822.      * @access public
  823.      *
  824.      */
  825.     function getType($key)
  826.     {
  827.         if (isset($this->configuration_info[$key])) {
  828.             return $this->configuration_info[$key]['type'];
  829.         }
  830.         return false;
  831.     }
  832.  
  833.     // }}}
  834.     // {{{ getDocs(key)
  835.  
  836.     /**
  837.      * Get the documentation for a config value.
  838.      *
  839.      * @param string  config key
  840.      *
  841.      * @return string documentation string
  842.      *
  843.      * @access public
  844.      *
  845.      */
  846.     function getDocs($key)
  847.     {
  848.         if (isset($this->configuration_info[$key])) {
  849.             return $this->configuration_info[$key]['doc'];
  850.         }
  851.         return false;
  852.     }
  853.        // }}}
  854.     // {{{ getPrompt(key)
  855.  
  856.     /**
  857.      * Get the short documentation for a config value.
  858.      *
  859.      * @param string  config key
  860.      *
  861.      * @return string short documentation string
  862.      *
  863.      * @access public
  864.      *
  865.      */
  866.     function getPrompt($key)
  867.     {
  868.         if (isset($this->configuration_info[$key])) {
  869.             return $this->configuration_info[$key]['prompt'];
  870.         }
  871.         return false;
  872.     }
  873.     // }}}
  874.     // {{{ getGroup(key)
  875.  
  876.     /**
  877.      * Get the parameter group for a config key.
  878.      *
  879.      * @param string  config key
  880.      *
  881.      * @return string parameter group
  882.      *
  883.      * @access public
  884.      *
  885.      */
  886.     function getGroup($key)
  887.     {
  888.         if (isset($this->configuration_info[$key])) {
  889.             return $this->configuration_info[$key]['group'];
  890.         }
  891.         return false;
  892.     }
  893.  
  894.     // }}}
  895.     // {{{ getGroups()
  896.  
  897.     /**
  898.      * Get the list of parameter groups.
  899.      *
  900.      * @return array list of parameter groups
  901.      *
  902.      * @access public
  903.      *
  904.      */
  905.     function getGroups()
  906.     {
  907.         $tmp = array();
  908.         foreach ($this->configuration_info as $key => $info) {
  909.             $tmp[$info['group']] = 1;
  910.         }
  911.         return array_keys($tmp);
  912.     }
  913.  
  914.     // }}}
  915.     // {{{ getGroupKeys()
  916.  
  917.     /**
  918.      * Get the list of the parameters in a group.
  919.      *
  920.      * @param string $group parameter group
  921.      *
  922.      * @return array list of parameters in $group
  923.      *
  924.      * @access public
  925.      *
  926.      */
  927.     function getGroupKeys($group)
  928.     {
  929.         $keys = array();
  930.         foreach ($this->configuration_info as $key => $info) {
  931.             if ($info['group'] == $group) {
  932.                 $keys[] = $key;
  933.             }
  934.         }
  935.         return $keys;
  936.     }
  937.  
  938.     // }}}
  939.     // {{{ getSetValues(key)
  940.  
  941.     /**
  942.      * Get the list of allowed set values for a config value.  Returns
  943.      * NULL for config values that are not sets.
  944.      *
  945.      * @param string  config key
  946.      *
  947.      * @return array enumerated array of set values, or NULL if the
  948.      *               config key is unknown or not a set
  949.      *
  950.      * @access public
  951.      *
  952.      */
  953.     function getSetValues($key)
  954.     {
  955.         if (isset($this->configuration_info[$key]) &&
  956.             isset($this->configuration_info[$key]['type']) &&
  957.             $this->configuration_info[$key]['type'] == 'set')
  958.         {
  959.             $valid_set = $this->configuration_info[$key]['valid_set'];
  960.             reset($valid_set);
  961.             if (key($valid_set) === 0) {
  962.                 return $valid_set;
  963.             }
  964.             return array_keys($valid_set);
  965.         }
  966.         return false;
  967.     }
  968.  
  969.     // }}}
  970.     // {{{ getKeys()
  971.  
  972.     /**
  973.      * Get all the current config keys.
  974.      *
  975.      * @return array simple array of config keys
  976.      *
  977.      * @access public
  978.      */
  979.     function getKeys()
  980.     {
  981.         $keys = array();
  982.         foreach ($this->layers as $layer) {
  983.             $keys = array_merge($keys, $this->configuration[$layer]);
  984.         }
  985.         return array_keys($keys);
  986.     }
  987.  
  988.     // }}}
  989.     // {{{ remove(key, [layer])
  990.  
  991.     /**
  992.      * Remove the a config key from a specific config layer.
  993.      *
  994.      * @param string config key
  995.      *
  996.      * @param string (optional) config layer
  997.      *
  998.      * @return bool TRUE on success, FALSE on failure
  999.      *
  1000.      * @access public
  1001.      */
  1002.     function remove($key, $layer = 'user')
  1003.     {
  1004.         if (isset($this->configuration[$layer][$key])) {
  1005.             unset($this->configuration[$layer][$key]);
  1006.             return true;
  1007.         }
  1008.         return false;
  1009.     }
  1010.  
  1011.     // }}}
  1012.     // {{{ removeLayer(layer)
  1013.  
  1014.     /**
  1015.      * Temporarily remove an entire config layer.  USE WITH CARE!
  1016.      *
  1017.      * @param string config key
  1018.      *
  1019.      * @param string (optional) config layer
  1020.      *
  1021.      * @return bool TRUE on success, FALSE on failure
  1022.      *
  1023.      * @access public
  1024.      */
  1025.     function removeLayer($layer)
  1026.     {
  1027.         if (isset($this->configuration[$layer])) {
  1028.             $this->configuration[$layer] = array();
  1029.             return true;
  1030.         }
  1031.         return false;
  1032.     }
  1033.  
  1034.     // }}}
  1035.     // {{{ store([layer])
  1036.  
  1037.     /**
  1038.      * Stores configuration data in a layer.
  1039.      *
  1040.      * @param string config layer to store
  1041.      *
  1042.      * @return bool TRUE on success, or PEAR error on failure
  1043.      *
  1044.      * @access public
  1045.      */
  1046.     function store($layer = 'user', $data = null)
  1047.     {
  1048.         return $this->writeConfigFile(null, $layer, $data);
  1049.     }
  1050.  
  1051.     // }}}
  1052.     // {{{ toDefault(key)
  1053.  
  1054.     /**
  1055.      * Unset the user-defined value of a config key, reverting the
  1056.      * value to the system-defined one.
  1057.      *
  1058.      * @param string config key
  1059.      *
  1060.      * @return bool TRUE on success, FALSE on failure
  1061.      *
  1062.      * @access public
  1063.      */
  1064.     function toDefault($key)
  1065.     {
  1066.         trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE);
  1067.         return $this->remove($key, 'user');
  1068.     }
  1069.  
  1070.     // }}}
  1071.     // {{{ definedBy(key)
  1072.  
  1073.     /**
  1074.      * Tells what config layer that gets to define a key.
  1075.      *
  1076.      * @param string config key
  1077.      *
  1078.      * @return string the config layer, or an empty string if not found
  1079.      *
  1080.      * @access public
  1081.      */
  1082.     function definedBy($key)
  1083.     {
  1084.         foreach ($this->layers as $layer) {
  1085.             if (isset($this->configuration[$layer][$key])) {
  1086.                 return $layer;
  1087.             }
  1088.         }
  1089.         return '';
  1090.     }
  1091.  
  1092.     // }}}
  1093.     // {{{ isDefaulted(key)
  1094.  
  1095.     /**
  1096.      * Tells whether a config value has a system-defined value.
  1097.      *
  1098.      * @param string   config key
  1099.      *
  1100.      * @return bool
  1101.      *
  1102.      * @access public
  1103.      *
  1104.      * @deprecated
  1105.      */
  1106.     function isDefaulted($key)
  1107.     {
  1108.         trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE);
  1109.         return $this->definedBy($key) == 'system';
  1110.     }
  1111.  
  1112.     // }}}
  1113.     // {{{ isDefined(key)
  1114.  
  1115.     /**
  1116.      * Tells whether a given key exists as a config value.
  1117.      *
  1118.      * @param string config key
  1119.      *
  1120.      * @return bool whether <config key> exists in this object
  1121.      *
  1122.      * @access public
  1123.      */
  1124.     function isDefined($key)
  1125.     {
  1126.         foreach ($this->layers as $layer) {
  1127.             if (isset($this->configuration[$layer][$key])) {
  1128.                 return true;
  1129.             }
  1130.         }
  1131.         return false;
  1132.     }
  1133.  
  1134.     // }}}
  1135.     // {{{ isDefinedLayer(key)
  1136.  
  1137.     /**
  1138.      * Tells whether a given config layer exists.
  1139.      *
  1140.      * @param string config layer
  1141.      *
  1142.      * @return bool whether <config layer> exists in this object
  1143.      *
  1144.      * @access public
  1145.      */
  1146.     function isDefinedLayer($layer)
  1147.     {
  1148.         return isset($this->configuration[$layer]);
  1149.     }
  1150.  
  1151.     // }}}
  1152.     // {{{ getLayers()
  1153.  
  1154.     /**
  1155.      * Returns the layers defined (except the 'default' one)
  1156.      *
  1157.      * @return array of the defined layers
  1158.      */
  1159.     function getLayers()
  1160.     {
  1161.         $cf = $this->configuration;
  1162.         unset($cf['default']);
  1163.         return array_keys($cf);
  1164.     }
  1165.  
  1166.     // }}}
  1167. }
  1168.  
  1169. ?>
  1170.